package com.rytong.tools.crypto;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Random;

import javax.crypto.Cipher;

import android.app.Activity;
import android.content.Context;

import com.rytong.tools.utils.Utils;

public class RSACipher {
    public static final int PUBLIC_KEY = 0;
    public static final int PRIVATE_KEY = 1;

    public static final String PUBLIC_CER_MODULUS_FILENAME = "pubmodulus";
    public static final String PUBLIC_CER_EXPONENT_FILENAME = "pubexponent";
    public static final String PRIVATE_CER_MODULUS_FILENAME = "primodulus";
    public static final String PRIVATE_CER_EXPONENT_FILENAME = "priexponent";

    // public static final String TRANSFORMATION_RSA_ECB_PKCS1 = "RSA/ECB/NoPadding";
    public static final String TRANSFORMATION_RSA_ECB_PKCS1 = "RSA/ECB/PKCS1Padding";
    public static final String TRANSFORMATION_RSA_CBC_PKCS1 = "RSA/CBC/PKCS1Padding";

    // final static byte[] modulus = new byte[] { (byte) 0x00, (byte) 0xbe,
    // (byte) 0xc3, (byte) 0x62, (byte) 0xd2, (byte) 0xa8, (byte) 0x91,
    // (byte) 0x43, (byte) 0x91, (byte) 0x19, (byte) 0x73, (byte) 0x33,
    // (byte) 0xa8, (byte) 0x79, (byte) 0x6b, (byte) 0x08, (byte) 0x8c,
    // (byte) 0x13, (byte) 0x05, (byte) 0x2b, (byte) 0xb3, (byte) 0x0c,
    // (byte) 0xd1, (byte) 0xab, (byte) 0xa4, (byte) 0xf8, (byte) 0x7c,
    // (byte) 0x8b, (byte) 0x45, (byte) 0xa9, (byte) 0xc7, (byte) 0xc5,
    // (byte) 0x12, (byte) 0x16, (byte) 0x9a, (byte) 0xe8, (byte) 0xb4,
    // (byte) 0xa3, (byte) 0xfe, (byte) 0x9d, (byte) 0x60, (byte) 0x51,
    // (byte) 0x51, (byte) 0xc0, (byte) 0x8c, (byte) 0x67, (byte) 0x1c,
    // (byte) 0xa3, (byte) 0x96, (byte) 0x40, (byte) 0x4c, (byte) 0x68,
    // (byte) 0x16, (byte) 0xd6, (byte) 0x23, (byte) 0xfb, (byte) 0x04,
    // (byte) 0x73, (byte) 0xfc, (byte) 0x62, (byte) 0xbe, (byte) 0x42,
    // (byte) 0x38, (byte) 0x6c, (byte) 0x9b, (byte) 0xd5, (byte) 0xe0,
    // (byte) 0xdd, (byte) 0x7e, (byte) 0xcd, (byte) 0xfd, (byte) 0x22,
    // (byte) 0x6b, (byte) 0xa4, (byte) 0x8a, (byte) 0x17, (byte) 0x76,
    // (byte) 0x51, (byte) 0x73, (byte) 0xd9, (byte) 0xf6, (byte) 0x98,
    // (byte) 0xe9, (byte) 0xbb, (byte) 0xaf, (byte) 0x35, (byte) 0x84,
    // (byte) 0xfb, (byte) 0xcc, (byte) 0x6a, (byte) 0x1a, (byte) 0x98,
    // (byte) 0x81, (byte) 0x1d, (byte) 0x09, (byte) 0xe0, (byte) 0x77,
    // (byte) 0xe8, (byte) 0x29, (byte) 0x1c, (byte) 0x52, (byte) 0xf9,
    // (byte) 0x14, (byte) 0x22, (byte) 0x08, (byte) 0xc4, (byte) 0xdc,
    // (byte) 0x56, (byte) 0x07, (byte) 0x98, (byte) 0x83, (byte) 0x63,
    // (byte) 0xcf, (byte) 0x2d, (byte) 0x4b, (byte) 0xf4, (byte) 0x12,
    // (byte) 0xaa, (byte) 0xd9, (byte) 0x84, (byte) 0xcf, (byte) 0x0f,
    // (byte) 0x65, (byte) 0xaf, (byte) 0xc6, (byte) 0x26, (byte) 0xef,
    // (byte) 0xad, (byte) 0xf9 };

    /* CEAIR Test */
    final static byte[] modulus = new byte[] { (byte) 0x00, (byte) 0xb3, (byte) 0x2e, (byte) 0x64, (byte) 0xfd,
            (byte) 0x74, (byte) 0x76, (byte) 0x2a, (byte) 0x28, (byte) 0x40, (byte) 0x4b, (byte) 0x6f, (byte) 0xdb,
            (byte) 0x2a, (byte) 0xd9, (byte) 0x2d, (byte) 0x10, (byte) 0x98, (byte) 0xf8, (byte) 0x2a, (byte) 0x3e,
            (byte) 0x27, (byte) 0xdb, (byte) 0x80, (byte) 0xf5, (byte) 0x26, (byte) 0xf0, (byte) 0x13, (byte) 0x67,
            (byte) 0xb4, (byte) 0xd9, (byte) 0x72, (byte) 0xa1, (byte) 0xc6, (byte) 0x9b, (byte) 0x5e, (byte) 0x97,
            (byte) 0x7c, (byte) 0x5d, (byte) 0xee, (byte) 0xc8, (byte) 0xb5, (byte) 0x46, (byte) 0x07, (byte) 0xf8,
            (byte) 0x7a, (byte) 0x3e, (byte) 0x10, (byte) 0x38, (byte) 0x4d, (byte) 0xad, (byte) 0x17, (byte) 0xf4,
            (byte) 0x36, (byte) 0xd9, (byte) 0xdb, (byte) 0xaf, (byte) 0xea, (byte) 0x0d, (byte) 0xac, (byte) 0x7c,
            (byte) 0x7f, (byte) 0xb3, (byte) 0xf3, (byte) 0x5c, (byte) 0x96, (byte) 0x00, (byte) 0x58, (byte) 0xa4,
            (byte) 0x89, (byte) 0xa8, (byte) 0x85, (byte) 0xdd, (byte) 0xa9, (byte) 0x8e, (byte) 0xb9, (byte) 0xab,
            (byte) 0x57, (byte) 0xa2, (byte) 0x8c, (byte) 0x73, (byte) 0x0b, (byte) 0x2c, (byte) 0xda, (byte) 0xe1,
            (byte) 0xb3, (byte) 0x1e, (byte) 0xd5, (byte) 0x45, (byte) 0xf8, (byte) 0xe9, (byte) 0x3b, (byte) 0x02,
            (byte) 0x97, (byte) 0x46, (byte) 0xcf, (byte) 0xd2, (byte) 0xa3, (byte) 0x48, (byte) 0xff, (byte) 0xff,
            (byte) 0x79, (byte) 0xd6, (byte) 0x7f, (byte) 0x02, (byte) 0x61, (byte) 0x38, (byte) 0x75, (byte) 0xf7,
            (byte) 0xfd, (byte) 0xea, (byte) 0x86, (byte) 0xec, (byte) 0xf9, (byte) 0xe1, (byte) 0xaa, (byte) 0xa6,
            (byte) 0xec, (byte) 0xd0, (byte) 0xfe, (byte) 0x3d, (byte) 0xb2, (byte) 0x72, (byte) 0x27, (byte) 0x4b,
            (byte) 0xec, (byte) 0x87, (byte) 0x45, (byte) 0x49 };
    final static String exponent = "65537";

    public static byte[] genEnvelopeKey(String userCode) throws Exception {
        byte[] bytes = null;
        try {
            bytes = new byte[8];
            Random rd = new Random();
            long time = System.currentTimeMillis();
            rd.setSeed(time);
            // the value of first byte is between 128 and 255
            int key = 129 + Math.abs(rd.nextInt()) % 128;
            bytes[0] = (byte) key;

            int cnt = 7;
            do {
                int tmp = Math.abs(rd.nextInt()) % 255;
                bytes[8 - cnt] = (byte) tmp;
                cnt--;
            } while (cnt > 0);

            // there should NOT '=' at the end of the string, so remove '='.
            bytes = Base64.encode(bytes).substring(0, 8).getBytes("UTF-8");

            return bytes;
            /*
             * String str = Integer.toString(rd.nextInt()) + Long.toString(time) + userCode; String hash =
             * LPUtils.sha1(str); LPUtils.printOutToConsole("hash-->" + hash); return hash.substring(0, 8);
             */

        } catch (Exception ex) {
            throw new Exception("创建密钥出错!");
        }
    }

    private RSAPublicKeySpec ImportPublicKey(byte[] mod, String exp) throws Exception {
        RSAPublicKeySpec RSAParam = null;
        BigInteger mypubkey_modulus = null;
        BigInteger mypubkey_exponent = null;
        try {
            mypubkey_modulus = new BigInteger(mod);
            mypubkey_exponent = new BigInteger(exp);
            RSAParam = new RSAPublicKeySpec(mypubkey_modulus, mypubkey_exponent);
        } catch (Exception e) {
            throw new Exception("无法取得公钥！");
        }
        return RSAParam;
    }

    /**
     * @param paintText
     * @param transformation
     *            TODO
     * @return
     * @throws Exception
     */
    public static String doEncryptWithCertUserArr(byte[] paintText, String transformation) throws Exception {
        RSAPublicKey rsaPubKey = getPublicKey();
        String cipherText = doEncryptWithBase64(paintText, rsaPubKey, transformation);
        return cipherText;
    }

    /**
     * @param paintText
     * @param rsaPubKey
     * @param transformation
     * @return
     * @throws Exception
     */
    public static String doEncryptWithBase64(byte[] paintText, RSAPublicKey rsaPubKey, String transformation)
            throws Exception {
        String cipherText = null;
        try {
            byte[] original = doEncrypt(paintText, rsaPubKey, transformation);
            String enData = Base64.encode(original);
            cipherText = removeRN(enData);
        } catch (Exception ex) {
            throw new Exception("RSA加密出出错！");
        }
        return cipherText;
    }

    /**
     * @param paintText
     * @param rsaPubKey
     * @param transformation
     * @return
     * @throws Exception
     */
    public static byte[] doEncrypt(final byte[] paintText, final RSAPublicKey rsaPubKey, final String transformation)
            throws Exception {
        byte[] cipherMsg = null;
        try {
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(Cipher.ENCRYPT_MODE, rsaPubKey);
            cipherMsg = cipher.doFinal(paintText);
        } catch (Exception ex) {
            throw new Exception("RSA加密出出错！");
        }
        return cipherMsg;
    }

    /**
     * @return
     * @throws NoSuchAlgorithmException
     * @throws Exception
     * @throws InvalidKeySpecException
     */
    public static RSAPublicKey getPublicKey() throws NoSuchAlgorithmException, Exception, InvalidKeySpecException {
        KeyFactory keyFac = KeyFactory.getInstance("RSA");
        RSACipher ciper = new RSACipher();
        RSAPublicKeySpec pubKey = ciper.ImportPublicKey(modulus, exponent);
        RSAPublicKey rsaPubKey = (RSAPublicKey) keyFac.generatePublic(pubKey);
        return rsaPubKey;
    }

    /**
     * 加密
     * 
     * @param key
     *            加密的密钥
     * @param data
     *            待加密的明文数据
     * @return 加密后的数据
     * @throws Exception
     */
    public static byte[] encrypt(Key key, byte[] data) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            int blockSize = cipher.getBlockSize();
            int outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小
            int leavedSize = data.length % blockSize;
            int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
            byte[] raw = new byte[outputSize * blocksSize];
            int i = 0;
            while (data.length - i * blockSize > 0) {
                if (data.length - i * blockSize > blockSize)
                    cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
                else
                    cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
                // 这里面doUpdate方法不可用，查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中，而最后doFinal的时候才将所有的byte[]进行加密，可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
                i++;
            }
            return raw;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

    /**
     * remove all "\r\n"
     * 
     * @param str
     * @return
     * @throws Exception
     */
    private static String removeRN(String str) throws Exception {
        if (str == null)
            return null;
        int start = 0;
        int len = str.length();
        int id = str.indexOf("\r\n");
        StringBuffer sb = new StringBuffer();
        while (id != -1 && start < len) {
            sb.append(str.substring(start, id));
            start = id + 2;
            id = str.indexOf("\r\n", start);
        }
        if (start < len)
            sb.append(str.substring(start));
        return sb.toString();
    }

    /**
     * @param originData
     * @param signedData
     * @return
     * @throws Exception
     */
    public static boolean verifySign(byte[] originData, byte[] signedData) throws Exception {
        String cerPath = "test.cer";
        Certificate cert = getCertificate(cerPath);
        Signature signature = null;
        signature = Signature.getInstance("SHA1withDSA");
        signature.initVerify(cert.getPublicKey());
        signature.update(originData);
        return signature.verify(signedData);
    }

    /**
     * @param cer
     * @param pubkey
     * @return
     */
    public static boolean verifySign(Certificate cer, PublicKey pubkey) {
        try {
            cer.verify(pubkey);
        } catch (InvalidKeyException e) {
            Utils.printException(e);
            return false;
        } catch (CertificateException e) {
            Utils.printException(e);
            return false;
        } catch (NoSuchAlgorithmException e) {
            Utils.printException(e);
            return false;
        } catch (NoSuchProviderException e) {
            Utils.printException(e);
            return false;
        } catch (SignatureException e) {
            Utils.printException(e);
            return false;
        } catch (Exception e) {
            Utils.printException(e);
            return false;
        }
        return true;
    }

    /**
     * @param cerPath
     * @return
     * @throws FileNotFoundException
     * @throws CertificateException
     */
    public static Certificate getCertificate(String cerPath) throws FileNotFoundException, CertificateException {
        InputStream streamCert = new java.io.FileInputStream(cerPath);
        Certificate cert = getCertificate(streamCert);
        return cert;
    }

    /**
     * @param streamCert
     * @return
     * @throws CertificateException
     */
    public static X509Certificate getCertificate(InputStream streamCert) throws CertificateException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) factory.generateCertificate(streamCert);
        return cert;
    }

    /**
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[][] createKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        byte[][] keys = new byte[2][];
        keys[PUBLIC_KEY] = publicKeyBytes;
        keys[PRIVATE_KEY] = privateKeyBytes;
        return keys;
    }

    /**
     * Create KeyPair.
     * 
     * @return KeyPair
     * @throws Exception
     */
    public static KeyPair generateKeyPair() throws Exception {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            final int KEY_SIZE = 1024;
            keyPairGen.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGen.genKeyPair();
            return keyPair;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

    /**
     * Create RSA PublicKey.
     * 
     * @param modulus
     * @param publicExponent
     * @return RSAPublicKey
     * @throws Exception
     */
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws Exception {
        KeyFactory keyFac = null;
        try {
            keyFac = KeyFactory.getInstance("RSA");
        } catch (NoSuchAlgorithmException ex) {
            throw new Exception(ex.getMessage());
        }
        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
        try {
            return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
        } catch (InvalidKeySpecException ex) {
            throw new Exception(ex.getMessage());
        }
    }

    /**
     * Create RSA PrivateKey.
     * 
     * @param modulus
     * @param privateExponent
     * @return RSAPrivateKey
     * @throws Exception
     */
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws Exception {
        KeyFactory keyFac = null;
        try {
            keyFac = KeyFactory.getInstance("RSA");
        } catch (NoSuchAlgorithmException ex) {
            throw new Exception(ex.getMessage());
        }
        RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
        try {
            return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
        } catch (InvalidKeySpecException ex) {
            throw new Exception(ex.getMessage());
        }
    }

    /**
     * Create Certificate File.
     * 
     * @param byts
     * @param cerFile
     * @throws IOException
     */
    public static void genCerFile(byte byts[], String cerFile) throws FileNotFoundException, IOException {
        FileOutputStream out = new FileOutputStream(cerFile);
        out.write(byts);
        out.flush();
        out.close();
    }

    /**
     * @param cerFile
     * @return
     * @throws FileNotFoundException
     */
    public static byte[] readCerFile(String cerFile) throws FileNotFoundException, IOException {
        FileInputStream in = new FileInputStream(cerFile);
        int size = in.available();
        byte[] cerByts = new byte[size];
        int offset = in.read(cerByts);
        return cerByts;
    }

    public static void main(String[] args) throws Exception {
        String str = "hello,有中文的情况";
        Utils.printOutToConsole("原文：" + str);
        RSACipher rsa = new RSACipher();
        RSAPrivateKey privateKey = (RSAPrivateKey) Utils.readFromFile(null, "sk.dat");
        RSAPublicKey publickKey = (RSAPublicKey) Utils.readFromFile(null, "pk.dat");
        byte[] encbyte = rsa.encrypt(str, privateKey);
        Utils.printOutToConsole("私钥加密后：");
        String encStr = toHexString(encbyte);
        Utils.printOutToConsole(encStr);
        byte[] signBytes = rsa.sign(str, privateKey);
        Utils.printOutToConsole("签名值：");
        String signStr = toHexString(signBytes);
        Utils.printOutToConsole(signStr);
        byte[] decByte = rsa.decrypt(encStr, publickKey);
        Utils.printOutToConsole("公钥解密后：");
        String decStr = new String(decByte);
        Utils.printOutToConsole(decStr);
        if (rsa.verifySign(str, signStr, publickKey)) {
            Utils.printOutToConsole("rsa sign check success");
        } else {
            Utils.printOutToConsole("rsa sign check failure");
        }
    }

    /** * 加密,key可以是公钥，也可以是私钥 * * @param message * @return * @throws Exception */
    public byte[] encrypt(String message, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(toBytes(message));
        // return cipher.doFinal(message.getBytes());
    }

    /** * 加密,key可以是公钥，也可以是私钥 * * @param message * @return * @throws Exception */
    public byte[] encrypt(byte[] message, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(message);
    }

    /** * 解密，key可以是公钥，也可以是私钥，如果是公钥加密就用私钥解密，反之亦然 * * @param message * @return * @throws Exception */
    public byte[] decrypt(byte[] message, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(message);
    }

    /** * 解密，key可以是公钥，也可以是私钥，如果是公钥加密就用私钥解密，反之亦然 * * @param message * @return * @throws Exception */
    public byte[] decrypt(String message, Key key) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(toBytes(message));
    }

    /** * 用私钥签名 * * @param message * @param key * @return * @throws Exception */
    public byte[] sign(String message, PrivateKey key) throws Exception {
        Signature signetcheck = Signature.getInstance("MD5withRSA");
        signetcheck.initSign(key);
        signetcheck.update(message.getBytes("ISO-8859-1"));
        return signetcheck.sign();
    }

    /** * 用公钥验证签名的正确性 * * @param message * @param signStr * @return * @throws Exception */
    public boolean verifySign(String message, String signStr, PublicKey key) throws Exception {
        if (message == null || signStr == null || key == null) {
            return false;
        }
        Signature signetcheck = Signature.getInstance("MD5withRSA");
        signetcheck.initVerify(key);
        signetcheck.update(message.getBytes("ISO-8859-1"));
        //
        return signetcheck.verify(signStr.getBytes());
    }

    public static String toHexString(byte[] b) {
        StringBuilder sb = new StringBuilder(b.length << 1);
        for (int i = 0; i < b.length; i++) {
            sb.append(HEXCHAR[(b[i] & 0xf0) >>> 4]);
            sb.append(HEXCHAR[b[i] & 0x0f]);
        }
        return sb.toString();
    }

    public static final byte[] toBytes(String s) {
        byte[] bytes;
        bytes = new byte[s.length() >> 1];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(s.substring(i << 1, (i << 1) + 2), 16);
        }
        return bytes;
    }

    /** * 根据keyInfo产生公钥和私钥，并且保存到pk.dat和sk.dat文件中 * * @param keyInfo * @throws Exception */
    /**
     * 
     * @param bv
     * @param keyInfo
     *            加密种子信息
     * @throws Exception
     */
    public void genKeys(Activity bv, String keyInfo) throws Exception {
        KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = new SecureRandom();
        random.setSeed(keyInfo.getBytes());
        // 初始加密，长度为1024，必须是大于1024才可以的
        keygen.initialize(1024, random);
        // 取得密钥对
        KeyPair kp = keygen.generateKeyPair();
        // 取得公钥
        PublicKey publicKey = kp.getPublic();
        Utils.printOutToConsole(publicKey);
        Utils.saveFile(bv, publicKey, "pk.dat");
        // 取得私钥
        PrivateKey privateKey = kp.getPrivate();

        Utils.printOutToConsole(privateKey);
        Utils.saveFile(bv, privateKey, "sk.dat");
    }

    public PublicKey getPublicKey(String modulus, String publicExponent) throws Exception {

        BigInteger m = new BigInteger(modulus);

        BigInteger e = new BigInteger(publicExponent);

        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        return publicKey;

    }

    public PrivateKey getPrivateKey(String modulus, String privateExponent) throws Exception {

        BigInteger m = new BigInteger(modulus);

        BigInteger e = new BigInteger(privateExponent);

        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        return privateKey;

    }

    private static char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}
